#include "PixelProcessor.h"

using namespace std;

PixelProcessor::PixelProcessor(void)
{
  NorthPixel = NULL;
  NorthEastPixel = NULL;
  EastPixel = NULL;
  SouthEastPixel = NULL;
  SouthPixel = NULL;
  SouthWestPixel = NULL;
  WestPixel = NULL;
  NorthWestPixel = NULL;

  /* NOTE: allocating memory */
  PixelLabel = new Label;

  //m_pixelValue = 0;
  m_currentClockedAddressBit = 0;
  m_pixelAddress = 0;
  m_currentClockedBit = 0;

  m_currentAddressingMode = SENDING_ADDRESS;
}

PixelProcessor::~PixelProcessor(void)
{
  /* NOTE: releasing memory */
  delete PixelLabel;
}

void PixelProcessor::ClockProcessor(void)
{
  m_currentClockedBit++;
  ClockAddressBit();
}

bool PixelProcessor::GetClockedDataBit(void)
{
  return bClockedDataBit;
}

void PixelProcessor::SetDataLine(bool dataBit)
{
  bDataLine = dataBit;
}

void PixelProcessor::SetPixelPosition(int x, int y)
{
  m_xLocation = x;
  m_yLocation = y;
}

void PixelProcessor::SetPixelValue(bool pixel)
{
  m_pixelValue = pixel;
}

void PixelProcessor::SetPixelAddress(unsigned int address)
{
  m_pixelAddress = address;
  m_currentClockedBit = 0;
  ClockAddressBit();
}

bool PixelProcessor::GetClockedAddressBit(void)
{
  return m_currentClockedAddressBit;
}

void PixelProcessor::ClockAddressBit(void)
{
  unsigned int shiftReg = 0x80000000;

  if(m_currentClockedBit < ((sizeof(m_pixelAddress) * 8) + 1))
  {
    m_currentClockedAddressBit = (0 != (m_pixelAddress & 
                                       (shiftReg >> m_currentClockedBit)));
  }
}

void PixelProcessor::SetBitInPixelLabel(bool LabelBit)
{  
  unsigned int shiftReg = 0x80000000;

  if(m_currentClockedAddressBit < (sizeof(m_pixelAddress)))
  {
    if(LabelBit)
    {
      m_pixelLabel |= (shiftReg >> m_currentClockedAddressBit);
    }
  }

}

void PixelProcessor::ClockNeighborAddressBit(void)
{

  bool shadow = NorthPixel->GetClockedAddressBit()        |
                NorthEastPixel->GetClockedAddressBit()    |
                EastPixel->GetClockedAddressBit()         |
                SouthEastPixel->GetClockedAddressBit()    |
                SouthPixel->GetClockedAddressBit()        |
                SouthWestPixel->GetClockedAddressBit()    |
                WestPixel->GetClockedAddressBit()         |
                NorthWestPixel->GetClockedAddressBit();

  if(shadow)
  {
    if(!m_currentClockedAddressBit)
    {
      m_currentAddressingMode = RECIEVING_ADDRESS;
    }
  }

  if(NULL != NorthPixel)
  {
    if(SENDING_ADDRESS == m_currentAddressingMode)
    {
      if(VerifyAgainstAddress(NorthPixel->GetClockedAddressBit()))
      {
        NorthPixel = NULL;
      }
    }
    else
    {
      if(shadow && !NorthPixel->GetClockedAddressBit())
      {
        NorthPixel = NULL;
      }
    }
  }

  if(NULL != NorthEastPixel)
  {
    if(SENDING_ADDRESS == m_currentAddressingMode)
    {
      if(VerifyAgainstAddress(NorthEastPixel->GetClockedAddressBit()))
      {
        NorthEastPixel = NULL;
      }
    }
    else
    {
      if(shadow && !NorthEastPixel->GetClockedAddressBit())
      {
        NorthEastPixel = NULL;
      }
    }
  }

  if(NULL != EastPixel)
  {
    if(SENDING_ADDRESS == m_currentAddressingMode)
    {
      if(VerifyAgainstAddress(EastPixel->GetClockedAddressBit()))
      {
        EastPixel = NULL;
      }
    }
    else
    {
      if(shadow && !EastPixel->GetClockedAddressBit())
      {
        EastPixel = NULL;
      }
    }
  }

  if(NULL != SouthEastPixel)
  {
    if(SENDING_ADDRESS == m_currentAddressingMode)
    {
      if(VerifyAgainstAddress(SouthEastPixel->GetClockedAddressBit()))
      {
        SouthEastPixel = NULL;
      }
    }
    else
    {
      if(shadow && !SouthEastPixel->GetClockedAddressBit())
      {
        SouthEastPixel = NULL;
      }
    }
  }

  if(NULL != SouthPixel)
  {
    if(SENDING_ADDRESS == m_currentAddressingMode)
    {
      if(VerifyAgainstAddress(SouthPixel->GetClockedAddressBit()))
      {
        SouthPixel = NULL;
      }
    }
    else
    {
      if(shadow && !SouthPixel->GetClockedAddressBit())
      {
        SouthPixel = NULL;
      }
    }
  }

  if(NULL != SouthWestPixel)
  {
    if(SENDING_ADDRESS == m_currentAddressingMode)
    {
      if(VerifyAgainstAddress(SouthWestPixel->GetClockedAddressBit()))
      {
        SouthWestPixel = NULL;
      }
    }
    else
    {
      if(shadow && !SouthWestPixel->GetClockedAddressBit())
      {
        SouthWestPixel = NULL;
      }
    }
  }

  if(NULL != WestPixel)
  {
    if(SENDING_ADDRESS == m_currentAddressingMode)
    {
      if(VerifyAgainstAddress(WestPixel->GetClockedAddressBit()))
      {
        WestPixel = NULL;
      }
    }
    else
    {
      if(shadow && !WestPixel->GetClockedAddressBit())
      {
        WestPixel = NULL;
      }
    }
  }

  if(NULL != NorthWestPixel)
  {
    if(SENDING_ADDRESS == m_currentAddressingMode)
    {
      if(VerifyAgainstAddress(NorthWestPixel->GetClockedAddressBit()))
      {
        NorthWestPixel = NULL;
      }
    }
    else
    {
      if(shadow && !NorthWestPixel->GetClockedAddressBit())
      {
        NorthWestPixel = NULL;
      }
    }
  }
}

bool PixelProcessor::VerifyAgainstAddress(bool AddressBit)
{
  if(m_currentClockedAddressBit)
  {
    if(AddressBit)
    {
      /* do nothing, both equal */
    }
    else
    {
      /* this processor is dominant, so quiet listening to neighbor processor */
      return 1;
    }
  }
  else
  {
    if(AddressBit)
    {
      /* this neighbor processor is dominant */
      /* quit transmitting and just listen for the new label */
      m_currentAddressingMode = RECIEVING_ADDRESS;
    }
  }
  return 0;
}

void PixelProcessor::SetNorthPixelObj(PixelProcessor * PixelPtr)
{
  if( NULL != PixelPtr )
  {
    if(PixelPtr->GetPixelValue())
    {
      NorthPixel = PixelPtr;
    }
  }
}

void PixelProcessor::SetNorthEastPixelObj(PixelProcessor * PixelPtr)
{
  if( NULL != PixelPtr )
  {
    if(PixelPtr->GetPixelValue())
    {
      NorthEastPixel = PixelPtr;
    }
  }
}

void PixelProcessor::SetEastPixelObj(PixelProcessor * PixelPtr)
{
  if( NULL != PixelPtr )
  {
    if(PixelPtr->GetPixelValue())
    {
      EastPixel = PixelPtr;
    }
  }
}

void PixelProcessor::SetSouthEastPixelObj(PixelProcessor * PixelPtr)
{
  if( NULL != PixelPtr )
  {
    if(PixelPtr->GetPixelValue())
    {
      SouthEastPixel = PixelPtr;
    }
  }
}

void PixelProcessor::SetSouthPixelObj(PixelProcessor * PixelPtr)
{
  if( NULL != PixelPtr )
  {
    if(PixelPtr->GetPixelValue())
    {
      SouthPixel = PixelPtr;
    }
  }
}

void PixelProcessor::SetSouthWestPixelObj(PixelProcessor * PixelPtr)
{
  if( NULL != PixelPtr )
  {
    if(PixelPtr->GetPixelValue())
    {
      SouthWestPixel = PixelPtr;
    }
  }
}

void PixelProcessor::SetWestPixelObj(PixelProcessor * PixelPtr)
{
  if( NULL != PixelPtr )
  {
    if(PixelPtr->GetPixelValue())
    {
      WestPixel = PixelPtr;
    }
  }
}

void PixelProcessor::SetNorthWestPixelObj(PixelProcessor * PixelPtr)
{
  if( NULL != PixelPtr )
  {
    if(PixelPtr->GetPixelValue())
    {
      NorthPixel = PixelPtr;
    }
  }
}

bool PixelProcessor::GetPixelValue(void)
{
  return m_pixelValue;
}
